using System;
using System.Collections.Generic;
using System.Text;

namespace RapidHDL
{
    class Decoder : TruthTableComponent
    {

        public NodeVector InputNodes;
        public NodeVector OutputNodes;

        public EncodeMap EncodeMap;

        public Decoder(Component poParentComponent, string psName, int piInputWidth, int piOutputWidth)
            : base(poParentComponent, psName)
        {
            InputNodes = this.CreateNodeVector("In", piInputWidth, NodeFlowType.Sink);
            OutputNodes = this.CreateNodeVector("Out", piOutputWidth, NodeFlowType.Source);
            OutputNodes.ForcedNodeStructure = NetStructure.Output;
            this.GetTruthTable("Decoder", piInputWidth, piOutputWidth);
            EncodeMap = new EncodeMap();
        }

        protected override void GenerateTruthTable()
        {
            int iInputWidth = InputNodes.Nodes.Count;
            int iOutputWidth = OutputNodes.Nodes.Count;

            string sInput;
            string sOutput;

            sOutput = new string('0', iOutputWidth);
            this.TruthTable.AddTableEntry("default", sOutput);			

            for (int iIn=0; iIn < iOutputWidth; iIn++)
            {
                sInput = Conversion.IntToBinaryString(iIn, iInputWidth);
                sOutput = new string('0', iOutputWidth - 1);
                sOutput = sOutput.Insert(iIn,"1");
                sOutput = Conversion.ReverseString(sOutput);
                this.TruthTable.AddTableEntry(sInput, sOutput);
            }
        }

        public override bool TransformStructureToVerilog()
        {
            WriteVerilogLookupTable();
            return true;
        }

        public Node NodeByName(string psName)
        {
            int iCode = EncodeMap.GetCode(psName);
            return OutputNodes[iCode];
        }

        public NodeVector BitByName(Component poParentComponent, string psName)
        {
            Node oNode = NodeByName(psName + "_" + psName);
            string sName = poParentComponent.NewNodeVectorName(oNode.Name);
            NodeVector nvBit = new NodeVector(poParentComponent, sName, 1);
            oNode.Net.Connect((Node)nvBit.Nodes[0]);
            return nvBit;
        }

    }
}
